class Snake {
    // 表示蛇头的元素
    head: HTMLElement;
    // 表示蛇的身体，包括蛇头
    bodies: HTMLCollection;
    // 获取蛇的容器
    element: HTMLElement;
    constructor() {
        this.element = document.getElementById('snake')!;
        this.head = document.querySelector('#snake > div')! as HTMLElement;//as 是类型断言
        this.bodies = this.element.getElementsByTagName('div')!;
    }
    // 获取蛇头的坐标
    get X() {
        return this.head.offsetLeft;
    }

    get Y() {
        return this.head.offsetTop;
    }
    // 设置蛇头的坐标
    set X(value: number) {
        // X值没变的话就不用进行后续判断和赋值操作了
        if (this.X == value) {
            return
        }
        // 撞墙检测
        if (value < 0 || value > 290) {
            throw new Error('蛇撞墙了');
        }
        // 水平移动时，不能掉头
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
            console.log('水平方向发生了掉头');
            // 如果发生掉头，让蛇向反方向继续行走
            if (value > this.X) {
                value = this.X - 10;
            } else {
                value = this.X + 10;
            }  
        }

        // 移动身体
        this.moveBody();

        this.head.style.left = value + 'px';

        // 检查是否撞到自己
        this.checkHead();
    }

    set Y(value: number) {
        // Y值没变的话就不用进行后续判断和赋值操作了
        if (this.Y == value) {
            return
        }
        // 撞墙检测
        if (value < 0 || value > 290) {
            throw new Error('蛇撞墙了');
        }
        // 上下移动时，不能掉头
        if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
            console.log('垂直方向发生了掉头');
            // 如果发生掉头，让蛇向反方向继续行走
            if (value > this.Y) {
                value = this.Y - 10;
            } else {
                value = this.Y + 10;
            }  
        }

        // 移动身体
        this.moveBody();

        this.head.style.top = value + 'px';

        // 检查是否撞到自己
        this.checkHead();
    }

    // 设置蛇增加身体的方法
    addBody() {
        // 向element里增加一个div
        this.element.insertAdjacentHTML("beforeend", "<div></div>");
    }

    // 蛇身体移动的方法
    /* 将后边的身体设置为前边身体的位置，从后往前设置 */
    moveBody() {
        // console.log(this.bodies.length);

        // 遍历获取所有的身体
        for (let i = this.bodies.length - 1; i > 0; i--) {
            // 获取前边身体的位置
            let fx = (this.bodies[i - 1] as HTMLElement).offsetLeft;
            let fy = (this.bodies[i - 1] as HTMLElement).offsetTop;

            // console.log(x,y);
            

            // 将上边的值设置给当前身体的位置
            (this.bodies[i] as HTMLElement).style.left = fx + 'px';
            (this.bodies[i] as HTMLElement).style.top = fy + 'px';
        }
    }

    // 检查蛇头是否撞到自己
    checkHead() {
        // 获取所有身体，检查是否和蛇头重叠
        for (let i = 1; i < this.bodies.length; i++) {
            let bd = this.bodies[i] as HTMLElement;
            if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
                // 蛇头撞到身体
                throw new Error('蛇头撞到身体')
            }
        }
    }
}

export default Snake;